#include <transform.h>
#include <vec4.h>
#include <log.h>
#include <math_tool.h>
#include <camera.h>

void test_translate() {
    Vec4f point{ 0, 0, 0, 1 };

    Mat4x4 transform = translate(Mat4x4::One(), Vec3f{ 5, 5, 5 });

    log(transform, "translate:\n");
    log(transform * point, "translate point:\n");
}

void test_rotate() {
    Vec4f point{ 1, 0, 0, 1 };

    Mat4x4 rotateX= rotate(Mat4x4::One(), radians(45.0f), Vec3f{ 1.0f, 0.0f, 0.0f });
    log(rotateX, "rotateX :\n");
    log(rotateX * point, "rotateX point:\n");

    Mat4x4 rotateY = rotate(Mat4x4::One(), radians(45.0f), Vec3f{ 0.0f, 1.0f, 0.0f });
    log(rotateY, "rotateY:\n");
    log(rotateY * point, "rotateY point:\n");

    Mat4x4 rotateZ = rotate(Mat4x4::One(), radians(45.0f), Vec3f{ 0.0f, 0.0f, 1.0f });
    log(rotateZ, "rotateZ:\n");
    log(rotateZ * point, "rotateZ point:\n");
}

void test_scale() {
    Vec4f point1{ -0.5f, -0.5f, -0.5f, 1.0f };
    Vec4f point2{ 0.5f, 0.5f, 0.5f, 1.0f };

    Mat4x4 transform = scale(Mat4x4::One(), Vec3f{ 5, 5, 5 });

    log(transform, "scale:\n");
    log(transform * point1, "scale point1:\n");
    log(transform * point2, "scale point2:\n");
}

void test_view() {
    Vec4f point{ 0.5f, 0.5f, 0.5f, 1.0f };

    Camera camera;
    // 移动摄影机
    camera.position = translate(Mat4x4::One(), { 0.0f, 0.0f, -5.0f }) * Vec4f{0, 0, 0, 1};

    Mat4x4 view = lookAt(camera.position, camera.center, camera.up);
    log(view, "view:\n");
    log(view * point, "view point:\n");

    // 左右旋转摄像机(绕up轴旋转)
    camera.position = Vec3f{};
    camera.center = rotate(Mat4x4::One(), radians(45.0f), Vec3f{0, 1, 0}) * Vec4f{0, 0, -1, 0}; 
    camera.up = rotate(Mat4x4::One(), radians(45.0f), Vec3f{0, 1, 0}) * Vec4f{0, 1, 0, 0}; 
    view = lookAt(camera.position, camera.center, camera.up);

    log(view, "rotate camera:\n");
    log(view * point, "view point:\n");

    // 上下旋转摄像机(绕cross(dir, up)轴旋转)
    camera.position = Vec3f{};
    camera.center = rotate(Mat4x4::One(), radians(45.0f), Vec3f{0, 1, 0}) * Vec4f{0, 0, -1, 0}; 
    camera.up = rotate(Mat4x4::One(), radians(45.0f), Vec3f{0, 1, 0}) * Vec4f{0, 1, 0, 0}; 
    view = lookAt(camera.position, camera.center, camera.up);

    log(view, "rotate camera:\n");
    log(view * point, "view point:\n");

    // 倾斜摄像机(绕dir轴旋转)
    camera.position = Vec3f{};
    camera.center = rotate(Mat4x4::One(), radians(45.0f), Vec3f{0, 0, -1}) * Vec4f{0, 0, -1, 0}; 
    camera.up = rotate(Mat4x4::One(), radians(45.0f), Vec3f{0, 0, -1}) * Vec4f{0, 1, 0, 0}; 
    view = lookAt(camera.position, camera.center, camera.up);

    log(view, "rotate camera:\n");
    log(view * Vec4f{0, 1, 0, 0}, "view point:\n");
}

void test_perspective() {
    Vec4f pointNearZ{0, 0, -1.0f, 1.0f};
    Vec4f pointMiddleZ{0, 0, (-1000.0f + 1.0f) / 2.0f, 1.0f};
    Vec4f pointFarZ{0, 0, -1000.0f, 1.0f};

    Mat4x4 proj = perspective(radians(60.0f), 800.0f / 720.0f, 1.0f, 1000.0f);

    log(proj, "proj:\n");
    log(divW(proj * pointNearZ), "pointNearZ point:\n");
    log(divW(proj * pointMiddleZ), "pointMiddleZ point:\n");
    log(divW(proj * pointFarZ), "pointFarZ point:\n");
}

void test_viewport() {
    Vec4f point{ 0.5f, 0.5f, 0.0f, 1.0f };

    Mat4x4 viewportMat = viewport(800, 800);

    log(point, "scale:\n");
    log(viewportMat, "viewportMat:\n");
    log(viewportMat * point, "viewport point:\n");
}

int main() {
    test_translate();
    test_rotate();
    test_scale();
    test_view();
    test_perspective();
    test_viewport();
}